//	---------------------------------------------------------------------------
//	Core_Services Web Application Framework vX.Y.Z
//	
//	Created By: Colm Hally( hallyu...ail.com )
//	Licensed Under GNU GPL Version 3 ( http://www.gnu.org/copyleft/gpl.html )
//	
//	Revision: 90
//	Date: 27th May 2009 01:30
//	----------------------------------------------------------------------------


(function() {

// Setup
var YES = true, NO = false, window = this, _cs = window.cs, Applications, 
	empty_function = function() {},
	Time = ( function() {
		return {
			now : function() { return Date.now ? Date.now() : new Date().getTime() },
			rel : function( t ) { t = t || this.now(); return t - this.load }, load : null, _load : null,
			prettyDate : function( time ) {
				// JavaScript Pretty Date; Copyright (c) 2008 John Resig ( jquery.com );
				// Licensed under the MIT license.

				// Takes an ISO time and returns a string representing how long ago the date represents.
					var date = new Date( time ), diff = ( ( ( new Date() ).getTime() - date.getTime() ) / 1000 ),
						day_diff = Math.floor( diff / 86400 );

					if ( isNaN( day_diff ) || day_diff < 0 ) return; // || day_diff >= 365

					return day_diff == 0 && (
							diff < 60 && 'just now' || diff < 120 && '1 minute ago' ||
							diff < 3600 && Math.floor( diff / 60 ) + ' minutes ago' ||
							diff < 7200 && '1 hour ago' ||
							diff < 86400 && Math.floor( diff / 3600 ) + ' hours ago' ) ||
						day_diff == 1 && 'Yesterday' || day_diff < 7 && day_diff + ' days ago' ||
						day_diff < 365 && Math.ceil( day_diff / 7 ) + ' weeks ago' ||
						day_diff > 365 && Math.ceil( day_diff / 365 ) + ' years ago';
			}
		}
	} )(),
	hasOwn = function( obj, prop ) { return Object.prototype.hasOwnProperty.call( obj, prop ) },
	default_options =  { title : 'Extensible WebApp Framework | CS', debug : YES }, // Delete .debug In Production
	ScriptFragment = '<script[^>]*>([\\S\\s]*?)<\/script>', JSONFilter = /^\/\*-secure-([\s\S]*)\*\/\s*$/,
	AES = ( function() {
		// The following is an AES implementation in JavaScript. (c) Chris Veness 2005-2008;
		function Cipher( input, w ) {
		  	var Nb = 4, Nr = w.length / Nb - 1, state = [ [], [], [], [] ];  
		  	for ( var i = 0; i < 4 * Nb; i++ ) state[ i % 4 ][ Math.floor( i / 4 ) ] = input[ i ];
		  	state = AddRoundKey( state, w, 0, Nb );
		  	for ( var round = 1; round < Nr; round++ ) {
		    	state = SubBytes( state, Nb ); state = ShiftRows( state, Nb );
		    	state = MixColumns( state, Nb ); state = AddRoundKey( state, w, round, Nb );
		  	}
		  	state = SubBytes( state, Nb ); state = ShiftRows( state, Nb );
		  	state = AddRoundKey( state, w, Nr, Nb );
		  	var output = new Array( 4 * Nb );  
		  	for ( var i = 0; i < 4 * Nb; i++ ) output[ i ] = state[ i % 4 ][ Math.floor( i / 4 ) ]; return output;
		}
		function SubBytes( s, Nb ) {
		  	for ( var r = 0; r < 4; r++ ) {
		    	for ( var c = 0; c < Nb; c++ ) s[ r ][ c ] = Sbox[ s[ r ][ c ] ];
		  	}; return s;
		}
		function ShiftRows( s, Nb ) {
		  	var t = new Array( 4 ); for ( var r = 1; r < 4; r++ ) {
		    	for ( var c = 0; c < 4; c++ ) t[ c ] = s[ r ][ ( c + r ) % Nb ];  
		    	for ( var c = 0; c < 4; c++ ) s[ r ][ c ] = t[ c ];         
		  	}; return s;  
		}
		function MixColumns( s, Nb ) {
		  	for ( var c = 0; c < 4; c++ ) {
		    	var a = new Array( 4 ), b = new Array( 4 );  
		    	for ( var i = 0; i < 4; i++ ) {
		      		a[ i ] = s[ i ][ c ];
		      		b[ i ] = s[ i ][ c ] & 0x80 ? s[ i ][ c ] << 1 ^ 0x011b : s[ i ][ c ] << 1;
		    	}

		    	s[ 0 ][ c ] = b[ 0 ] ^ a[ 1 ] ^ b[ 1 ] ^ a[ 2 ] ^ a[ 3 ]; 
		    	s[ 1 ][ c ] = a[ 0 ] ^ b[ 1 ] ^ a[ 2 ] ^ b[ 2 ] ^ a[ 3 ]; 
		    	s[ 2 ][ c ] = a[ 0 ] ^ a[ 1 ] ^ b[ 2 ] ^ a[ 3 ] ^ b[ 3 ]; 
		    	s[ 3 ][ c ] = a[ 0 ] ^ b[ 0 ] ^ a[ 1 ] ^ a[ 2 ] ^ b[ 3 ]; 
		  	}; return s;
		}
		function AddRoundKey( state, w, rnd, Nb ) {
		  	for ( var r = 0; r < 4; r++ ) {
		    	for ( var c = 0; c < Nb; c++ ) state[ r ][ c ] ^= w[ rnd * 4 + c ][ r ];
		  	}; return state;
		}
		function KeyExpansion( key ) {
		  	var Nb = 4, Nk = key.length / 4, Nr = Nk + 6,     
				w = new Array( Nb * ( Nr + 1 ) ), temp = new Array( 4 );

		  	for ( var i = 0; i < Nk; i++ ) {
		    	var r = [ key[ 4 * i ], key[ 4 * i + 1 ], key[ 4 * i + 2 ], key[ 4 * i + 3 ] ]; w[ i ] = r;
		  	}

		  	for ( var i = Nk; i < ( Nb * ( Nr + 1 ) ); i++ ) {
		    	w[ i ] = new Array( 4 );
		    	for ( var t = 0; t < 4; t++ ) temp[ t ] = w[ i - 1 ][ t ];
		    	if ( i % Nk == 0 ) {
		      		temp = SubWord( RotWord( temp ) );
		      		for ( var t = 0; t < 4; t++ ) temp[ t ] ^= Rcon[ i / Nk ][ t ];
		    	} else if ( Nk > 6 && i % Nk == 4 ) temp = SubWord( temp );
		    	for ( var t = 0; t < 4; t++ ) w[ i ][ t ] = w[ i - Nk ][ t ] ^ temp[ t ];
		  	}; return w;
		}
		function SubWord( w ) { for ( var i = 0; i < 4; i++ ) w[ i ] = Sbox[ w[ i ] ]; return w }
		function RotWord( w ) {
		  	var tmp = w[ 0 ]; for ( var i = 0; i < 3; i++ ) w[ i ] = w[ i + 1 ]; w[ 3 ] = tmp; return w;
		}
		var Sbox = ( function() {
			return [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
						0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
						0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
						0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
						0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
						0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
						0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
						0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
		             	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
		             	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
		             	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
		             	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
		             	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
		             	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
		             	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
		             	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16	];
		} )();
		var Rcon = ( function() {
			return [ [ 0x00, 0x00, 0x00, 0x00 ],
		             [ 0x01, 0x00, 0x00, 0x00 ],
		             [ 0x02, 0x00, 0x00, 0x00 ],
		             [ 0x04, 0x00, 0x00, 0x00 ],
		             [ 0x08, 0x00, 0x00, 0x00 ],
		             [ 0x10, 0x00, 0x00, 0x00 ],
		             [ 0x20, 0x00, 0x00, 0x00 ],
		             [ 0x40, 0x00, 0x00, 0x00 ],
		             [ 0x80, 0x00, 0x00, 0x00 ],
		             [ 0x1b, 0x00, 0x00, 0x00 ],
		             [ 0x36, 0x00, 0x00, 0x00 ] ];
		} )();
		var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		function encodeBase64( _str, utf8encode ) {  
		  	utf8encode =  ( typeof utf8encode == 'undefined' ) ? false : utf8encode;
		  	var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c, plain, coded;
		  	plain = utf8encode ? encodeUTF8( _str ) : _str; c = plain.length % 3;  
		  	if ( c > 0 ) { while ( c++ < 3 ) { pad += '='; plain += '\0'; } }
		  	for ( c = 0; c < plain.length; c+=3 ) {  
		    	o1 = plain.charCodeAt( c ); o2 = plain.charCodeAt( c + 1 ); o3 = plain.charCodeAt( c + 2 );
				bits = o1 << 16 | o2 << 8 | o3;
				h1 = bits >> 18 & 0x3f; h2 = bits >> 12 & 0x3f; h3 = bits >> 6 & 0x3f; h4 = bits & 0x3f;
				e[ c / 3 ] = b64.charAt( h1 ) + b64.charAt( h2 ) + b64.charAt( h3 ) + b64.charAt( h4 );
		  	}; coded = e.join( '' );  
			coded = coded.slice( 0, coded.length - pad.length ) + pad; return coded;
		}
		function decodeBase64( _str, utf8decode ) {
			utf8decode =  ( typeof utf8decode == 'undefined' ) ? false : utf8decode;
			var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded; coded = utf8decode ? decodeUTF8( _str ) : _str;
		  	for ( var c = 0; c < coded.length; c += 4 ) {  
		    	h1 = b64.indexOf( coded.charAt( c ) ); h2 = b64.indexOf( coded.charAt( c + 1 ) );
		    	h3 = b64.indexOf( coded.charAt( c + 2 ) ); h4 = b64.indexOf( coded.charAt( c + 3 ) );
				bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
				o1 = bits >>> 16 & 0xff; o2 = bits >>> 8 & 0xff; o3 = bits & 0xff;
				d[ c / 4 ] = String.fromCharCode( o1, o2, o3 );
				if ( h4 == 0x40 ) d[ c / 4 ] = String.fromCharCode( o1, o2 );
				if ( h3 == 0x40 ) d[ c / 4 ] = String.fromCharCode( o1 );
			}; plain = d.join( '' ); return utf8decode ? decodeUTF8( plain ) : plain; 
		}
		function encodeUTF8( _str ) {
		  	var str = _str.replace( /[\u0080-\u07ff ]/g, function( c ) { 
					var cc = c.charCodeAt( 0 ); return String.fromCharCode( 0xc0 | cc >> 6, 0x80 | cc & 0x3f );
			} );
		  	str = str.replace( /[\u0800-\uffff ]/g, function( c ) { 
		        	var cc = c.charCodeAt( 0 ); return String.fromCharCode( 0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3F, 0x80 | cc & 0x3f );
			} ); return str;
		}
		function decodeUTF8( _str ) {
		 	var str = _str.replace( /[\u00c0-\u00df ][\u0080-\u00bf ]/g, function( c ) {  
		        var cc = ( c.charCodeAt( 0 ) & 0x1f ) << 6 | c.charCodeAt( 1 ) & 0x3f; return String.fromCharCode( cc );
			} );
			str = str.replace( /[\u00e0-\u00ef ][\u0080-\u00bf ][\u0080-\u00bf ]/g, function( c ) {
		        var cc = ( ( c.charCodeAt( 0 ) & 0x0f ) << 12 ) | ( ( c.charCodeAt( 1 ) & 0x3f ) << 6 ) | ( c.charCodeAt( 2 ) & 0x3f ); 
		        return String.fromCharCode( cc );
			} ); return str;
		};
		
		function AESEncryptCtr( plaintext, password, nBits ) {
		  	var blockSize = 16;  
		  	if ( !( nBits == 128 || nBits == 192 || nBits == 256 ) ) return '';  
		  	plaintext = encodeUTF8( plaintext ); password = encodeUTF8( password );
		  	var nBytes = nBits / 8, pwBytes = new Array( nBytes );
		  	for ( var i = 0; i < nBytes; i++ ) {
		    	pwBytes[ i ] = isNaN( password.charCodeAt( i ) ) ? 0 : password.charCodeAt( i );
		  	}
		  	var key = Cipher( pwBytes, KeyExpansion( pwBytes ) ); key = key.concat( key.slice( 0, nBytes - 16 ) ),
		  		counterBlock = new Array( blockSize ), nonce = Time.now(), nonceSec = Math.floor( nonce / 1000 ),
				nonceMs = nonce % 1000;
		  	for ( var i = 0; i < 4; i++ ) counterBlock[ i ] = ( nonceSec >>> i * 8 ) & 0xff;
		  	for ( var i = 0; i < 4; i++ ) counterBlock[ i + 4 ] = nonceMs & 0xff; var ctrTxt = '';
		  	for ( var i = 0; i < 8; i++ ) ctrTxt += String.fromCharCode( counterBlock[ i ] );
		  	var keySchedule = KeyExpansion( key ), blockCount = Math.ceil( plaintext.length / blockSize ),
				ciphertxt = new Array( blockCount );  
		  	for ( var b = 0; b < blockCount; b++ ) {
		    	for ( var c = 0; c < 4; c++ ) counterBlock[ 15 - c ] = ( b >>> c * 8 ) & 0xff;
		    	for ( var c = 0; c < 4; c++ ) counterBlock[ 15 - c-4 ] = ( b / 0x100000000 >>> c * 8 );
		    	var cipherCntr = Cipher( counterBlock, keySchedule ),
		    		blockLength = b < blockCount - 1 ? blockSize : ( plaintext.length - 1 ) % blockSize + 1,
		    		cipherChar = new Array( blockLength );
		    	for ( var i = 0; i < blockLength; i++ ) {  
		      		cipherChar[ i ] = cipherCntr[ i ] ^ plaintext.charCodeAt( b * blockSize + i );
		      		cipherChar[ i ] = String.fromCharCode( cipherChar[ i ] );
		    	}; ciphertxt[ b ] = cipherChar.join( '' ); 
		  	}
		  	var ciphertext = ctrTxt + ciphertxt.join( '' ); ciphertext = encodeBase64( ciphertext ); return ciphertext;
		}
		function AESDecryptCtr( ciphertext, password, nBits ) {
		  	var blockSize = 16;  
		  	if ( !( nBits == 128 || nBits == 192 || nBits == 256 ) ) return '';  
		  	ciphertext = decodeBase64( ciphertext ); password = encodeUTF8( password );
		  	var nBytes = nBits / 8, pwBytes = new Array( nBytes );
		  	for ( var i = 0; i < nBytes; i++ ) {
		    	pwBytes[ i ] = isNaN( password.charCodeAt( i ) ) ? 0 : password.charCodeAt( i );
		  	}
		  	var key = Cipher( pwBytes, KeyExpansion( pwBytes ) ); key = key.concat( key.slice( 0, nBytes - 16 ) ),
				counterBlock = new Array( 8 ), ctrTxt = ciphertext.slice( 0, 8 );
		  	for ( var i = 0; i < 8; i++ ) counterBlock[ i ] = ctrTxt.charCodeAt( i );
		  	var keySchedule = KeyExpansion( key ), nBlocks = Math.ceil( ( ciphertext.length - 8 ) / blockSize ),
				ct = new Array( nBlocks );
		  	for ( var b = 0; b < nBlocks; b++ ) ct[ b ] = ciphertext.slice( 8 + b * blockSize, 8 + b * blockSize + blockSize );
		  	ciphertext = ct; var plaintxt = new Array( ciphertext.length );

		  	for ( var b = 0; b < nBlocks; b++ ) {
		    	for ( var c = 0; c < 4; c++ ) counterBlock[ 15 - c ] = ( ( b ) >>> c * 8 ) & 0xff;
		    	for ( var c = 0; c < 4; c++ ) counterBlock[ 15 - c-4 ] = ( ( ( b + 1 ) / 0x100000000 - 1 ) >>> c * 8 ) & 0xff;
		    	var cipherCntr = Cipher( counterBlock, keySchedule ), plaintxtByte = new Array( ciphertext[ b ].length );
		    	for ( var i = 0; i < ciphertext[ b ].length; i++ ) {
		      		plaintxtByte[ i ] = cipherCntr[ i ] ^ ciphertext[ b ].charCodeAt( i );
		      		plaintxtByte[ i ] = String.fromCharCode( plaintxtByte[ i ] );
		    	}; plaintxt[ b ] = plaintxtByte.join( '' );
		  	}
		  	var plaintext = plaintxt.join( '' ); plaintext = decodeUTF8( plaintext );  return plaintext;
		}
		return { encrypt : AESEncryptCtr, decrypt : AESDecryptCtr };
	} )();
	var $A = window.$A = function() {
		var args = Array.prototype.slice.call( arguments ); if ( 'toArray' in args[ 0 ] ) args[ 0 ] = args[ 0 ].toArray();
		return Array.prototype.slice.apply( args.shift(), args );
	},
	$F = window.$F = function( context, fn ) {
		if ( typeof fn != 'function' ) return empty_function; if ( !context ) return fn;
		return function() { return fn.apply( context, $A( arguments ) ) }
	}
var cs = window.cs = new core_services(); cs.extend( cs, 'native' );
	
// Some More Setup, After Initialisation
cs.options.defaults( default_options ); cs.title( YES ) // Set Defaults
Applications = ( function( cs ) {
	var Obj = {}; Obj.mem = {}; Obj.count = 0; Obj.csObjectType = 'ApplicationList';
	Obj.add = function( App ) {
		if ( cs.not( App, '+object' ) || cs.not( App.name, 'string|number' ) ) return NO;
		if ( cs.not( Obj.mem, 'object' ) ) return NO;
		Obj.mem[ App.name ] = App; Obj.count = cs.length( Obj.mem ); return App.name;
	};
	Obj.get = function( name ) {
		if ( cs.not( name, 'string|number' ) || cs.not( Obj.mem, 'object' ) ) return NO;
		if ( cs.not( Obj.mem[ name ], '+object' ) ) return NO;
			else return Obj.mem[ name ];
	};
	Obj.pop = function( name ) {
		var App = Obj.get( name ); if ( App === NO ) return NO;
		delete Obj.mem[ name ]; Obj.count = cs.length( Obj.mem ); return App;
	};
	Obj.extend = function( name, obj ) {
		var App = Obj.get( name ); if ( App === NO ) return NO;
		if ( !App.extend || cs.not( App.extend, 'function' ) ) return NO;
		if ( cs.not( obj, '-object' ) ) return NO; return App.extend( obj );
	};
	Obj.call = function( App, method, args ) {
		if ( cs.is( App, '-string' ) ) App = Obj.get( App ); if ( !App ) return null;
		if ( cs.not( method, '-string' ) || cs.not( App[ method ], '-function' ) ) return null;
		return App[ method ].apply( App, args );
	};
	Obj.propagate = function( method, args ) {
		if ( cs.not( method, 'string' ) ) return NO;
		var Apps = Obj.mem, ret = {};
		for ( var i in Apps ) { if ( !hasOwn( Apps, i ) ) continue;
			ret[ Apps[ i ].name ] = Obj.call( Apps[ i ], method, args );
		}; return ret;
	};
	return Obj;
})( cs );

Time.load = new Date().getTime(); // Set load time
cs.console.log( 'Core_Services Initialised', 1, new Date( Time._load ) ); cs.time = jQuery.extend( YES, {}, Time );

if ( cs.is( window.csReady, 'array' ) ) ( function() {
	var ready = window.csReady, i = ready.length;
	while( i-- ) { if ( cs.not( ready[ i ], '-function' ) ) continue; ready[ i ]( cs ) };
} )();

function core_services() {
	// Little Details
	this.version = '0.7.5'; this.csObjectType = 'Core_Services'; this.name = 'CS';
	this.YES = YES; this.NO = NO; this.info = { author : 'Colm Hally', license : 'GNU GPLv3' }
	this.time = null; // Set Later
	
	// Object Distinction Methods
	this.is = function( obj, types, collective ) {
		var is = $F( this, function( o, t, b ) { return t.toLowerCase() === this.type( o, b ) } ), ret;
		if ( ret = /^\-([0-9a-z_\-]+)/i.exec( types ) ) return typeof obj == ret[ 1 ];
		if ( ret = /^\+([0-9a-z\|_\-]+)/i.exec( types ) ) { var basic = YES, types = ret[ 1 ] }
		
		types = types.split( '|' ); var ret = NO, i, j, is_arr = is( obj, 'array', true ), is_obj = is( obj, 'object', true );
		if ( is_arr && collective === YES ) obj = $A( obj );
		if ( !collective ) {
			for ( i = 0; i < types.length; i++ ) { ret = ( ret === YES ) ? ret : is( obj, types[ i ], basic ); }; return ret;
		} else if ( is_arr || is_obj ) {
			for ( var i in obj ) {
				if ( is_obj && !hasOwn( obj, i ) ) continue;
				for ( j = 0; j < types.length; j++ ) { ret = YES; if ( is( obj[ i ], types[ j ], basic ) ) break; ret = NO }
				if ( ret === NO ) return NO;
			}; return YES;
		}; return NO;
	}
	this.not = function() { return !this.is.apply( this, arguments ) }
	this.type = function( obj, basic ) { // Returns a variable's type
		if ( obj === null ) return 'null'; if ( obj === undefined ) return 'undefined';
		// Return custom type
		if ( obj.csObjectType && !basic ) return obj.csObjectType.toLowerCase();
		// Return element nodename
		if ( obj.nodeType === 1 && !basic ) return obj.nodeName.toLowerCase();
		// Return the var's true type
		return /\[object (\w+)\]/i.exec( Object.prototype.toString.call( obj ) )[ 1 ].toLowerCase();
	}
	this.uid = function( key, constant ) {
		if ( cs.not( key, 'string' ) ) key = ( key.toString().length > 0 ) ? key.toString() : '';
		return ( constant === YES ) ? sha1( key ) : sha1( Time.now() + key );
	}
		
	// Extension Setup
	this.Extensions = ( function( cs ) {
		Dependencies = {
			Cache : [], Console : [], Options : [], Crypto : [], Events : [],
		};
		Constructors = {
			Cache : function( self ) {
				if ( cs.not( self, '+object' ) ) self = {}; cs.Extensions.init_dependencies( self, 'Cache' );

				var invalid = function( v ) { if ( cs.not( v, 'string|number|boolean' ) ) return YES; return NO };
				var update_count = function() { return this.count = cs.length( store ) }, name = self.name;
				var store = {}; this.count = 0;
				this.set = function( k, v, pw, b ) {
					if ( invalid( k ) ) return NO; if ( pw && b ) v = 'secure_' + AES.encrypt( v, pw, b);
					store[ k ] = v; return update_count();
				}
				this.get = function( k, pw, b ) {
					if ( invalid( k ) ) return NO; var v = store[ k ];
					if ( cs.is( v, '-string' ) ) var m = /^secure_([.\w\W\s\S\r\n]+)/.exec( v );
					if ( pw && b && m ) v = AES.decrypt( m[ 1 ], pw, b ); else if ( m ) return NO;
					return v;
				}
				this.remove = function( k ) {
					if ( invalid( k ) ) return NO; delete store[ k ]; update_count(); return update_count();
				}
				this.pop = function( k ) {
					if ( invalid( k ) ) return NO; var ret = this.get( k ); this.remove( k ); return ret;
				}
				this.each = function( fn ) { jQuery.each( store, fn ); return YES }
				this.get_all = function() {
					var ret = {}, i; for ( i in store ) { if ( !hasOwn( store, i ) ) continue; ret[ i ] = store[ i ] }; return ret
				}
				this.remove_all = function() {
					for ( var k in store ) { delete store[ k ] } update_count(); return YES;
				}
				this.remove_matching = function( str, opts ) {
					var matches = this.get_matching( str, opts ), k; if ( !matches ) return NO;
					for ( k in matches ) { if ( !hasOwn( matches, k ) ) continue; delete store[ k ] }; return update_count();
				}
				this.get_matching = function( str, opts ) {
					if ( invalid( str ) ) return NO;
					var tester = str.tester( opts ), ret = {};

					for ( var k in store ) {
						if ( !hasOwn( store, k ) ) continue; if ( tester( k ) ) ret[ k ] = store[ k ];
					}; ret.length = cs.length( ret ); return ret;
				}
				this.get_length = function() {
					var v = this.get.apply( this, arguments ); if ( !v ) return 0; return cs.length( v );
				}
			},
			Console : function( self ) {
				if ( cs.not( self, '+object' ) ) self = {}; cs.Extensions.init_dependencies( self, 'Console' );
				function exts() {
					var exts = cs.Extensions.list(), ret = {}, i;
					for ( i = 0; i < exts.length; i++ ) { var e = exts[ i ].toLowerCase();
						if ( cs.is( self[ e ], e ) ) ret[ e ] = YES; else ret[ e ] = NO;
					}; return ret;
				}
				var log_name = 'Console_Module_Log', cache = construct( 'Cache' ); cache.set( log_name, [] );
				this.log = function( val, level, time ) {
					if ( cs.not( val, 'string|number|boolean' ) && isNaN( val ) ) return NO; if ( cs.not( level, 'number' ) ) var level = 1;
					var time = ( cs.not( time, 'number|date' ) ) ? Time.now() : time;
					if ( exts().options && self.options.get( 'debug' ) && !( level < 0 ) ) console.log( val, '- ' + time );
					if ( level < 0 ) level *= -1;
					var log = this.get(), msg = { value : val, timestamp : time, level : level };
					log.push( msg ); cache.set( log_name, log ); this.count = log.length; return self;
				};
				this.get = function ( as_html ) {
					var log = cache.get( log_name ); if ( !as_html ) return log; var ret = '<div class="app_log" >';
					jQuery.each( log, function() {
						ret += '<div class="app_log_msg">'; ret += '<div class="app_log_level">' + this.level + '</div>';
						ret += '<div class="app_log_time">' + cs.is( this.timestamp, 'date' ) ? new Date( this.timestamp ).getTime() : this.timestamp + '</div>';
						ret += '<div class="app_log_value">' + this.value + '</div>'; ret += '</div>';
					} ); ret += '</div>'; return ret;
				}
			},
			Options : function( self ) {
				if ( cs.not( self, '+object' ) ) self = {};
				cs.Extensions.init_dependencies( self, 'Options' ); this.count = 0;
				var opts_name = 'Options_Module';
				function exts() {
					var exts = cs.Extensions.list(), ret = {}, i;
					for ( i = 0; i < exts.length; i++ ) { var e = exts[ i ].toLowerCase();
						if ( cs.is( self[ e ], e ) ) ret[ e ] = YES; else ret[ e ] = NO;
					}; return ret;
				}
				var cache = construct( 'Cache' ); cache.set( opts_name, {} );
				this.set = function( key, value ) {
					if ( cs.not( key, 'string|number|boolean' ) ) return NO;
					var opts = this.get_all(); var data = { option : key, old_value : opts[ key ], current_value : value }
					opts[ key ] = value; this.count = cs.length( opts ); cache.set( opts_name, opts );
					if ( exts().events ) self.events.trigger( 'option_change', data ); return value;
				}
				this.multi_set = function( opts ) {
					if ( cs.not( opts, 'object' ) ) return NO;
					for ( var i in opts ) {
						if ( !hasOwn( opts, i ) ) continue;
						this.set( i, opts[ i ] );
					}; return this.get_all();
				}
				this.get = function( key ) {
					if ( cs.not( key, 'string|number' ) ) return null; var opts = this.get_all(); return opts[ key ];
				}
				this.get_all = function() { return cache.get( opts_name ) }
				this.remove = function( key ) {
					if ( cs.not( key, 'string|number|boolean' ) ) return NO;
					var opts = this.get_all(), data = { option : key, old_value : opts[ key ], current_value : undefined }
					delete opts[ key ]; this.count = cs.length( opts ); cache.set( opts_name, opts );
					if ( exts().events ) self.events.trigger( 'option_change', data ); return this;
				}
				this.clean = function() {
					if ( exts().events ) self.events.trigger( 'options_clean' );
					cache.set( opts_name, {} ); this.count = 0; return this;
				}
				this.defaults = function( defs ) {
					if ( cs.not( defs, '+object' ) ) return NO;
					var cur_defs = cache.get( opts_name + '_Defaults' );
					if ( cs.is( cur_defs, '+object' ) ) jQuery.extend( cur_defs, defs ); else cur_defs = defs;

					cache.set( opts_name + '_Defaults', cur_defs ); this.multi_set( cur_defs );
					cache.set( opts_name + '_Defaults_Are_Setup', YES );
					if ( exts().console ) self.console.log( 'Defaults Set', -1 ); return this;
				}
				this.revert = function( opts ) {
					if ( cache.get( opts_name + '_Defaults_Are_Setup' ) !== YES ) return NO; var defs = cache.get( opts_name + '_Defaults' );
					if ( cs.not( opts, 'array' ) ) this.multi_set( defs )
					else {
						var curr = this.get_all();
						for ( var i = 0; i < this.count; i++ ) { var item = opts[ i ];
							if ( item in curr ) this.set( item, defs[ item ] );
						}
					}
					if ( exts().console ) self.console.log( 'Reverted To Defaults', -1 ); return this;
				}
				this.is = function( key, value ) {
					if ( cs.not( key, 'string|number|boolean' ) ) return NO; return this.get( key ) === value;
				}
				this.not = function() { return !this.is.apply( this, arguments ) }
			},
			Crypto : function( self ) {
				if ( cs.not( self, '+object' ) ) self = {}; cs.Extensions.init_dependencies( self, 'Crypto' );
				this.encrypt = function( _plaintext, _pwd, _bits ) { return AES.encrypt( _plaintext, _pwd, _bits ) }
				this.decrypt = function( _ciphertext, _pwd, _bits ) { return AES.decrypt( _ciphertext, _pwd, _bits ) }
			},
			Events : function( self ) {
				if ( cs.not( self, '+object' ) ) self = {}; cs.Extensions.init_dependencies( self, 'Events' );
				var events = construct( 'Cache' );
				function list_uids( name ) {
					var ret = {}, event = events.get( name ); if ( cs.not( event, '+array' ) ) return {};
					for ( var i = 0; i < event.length; i++ ) { ret[ event[ i ].uid ] = i }; return ret;
				}
				this.bind = function( name, fn ) {
					if ( cs.not( name, 'string' ) || cs.not( fn, 'function' ) ) return NO;
					var list = events.get( name ), uid = cs.uid( fn, YES );
					if ( !list ) var list = []; if ( list_uids( name )[ uid ] >= 0 ) return list.length;
					list.push( { fn : fn, uid : uid } );
					events.set( name, list ); return this;
				}
				this.unbind = function( name, fn ) {
					if ( cs.not( name, 'string' ) || cs.not( fn, 'function' ) ) return NO;
					var list = events.get( name ), uid = cs.uid( fn, YES ), uids = list_uids( name );
					if ( cs.not( list, '+array' ) ) return 0;
					if ( uids[ uid ] >= 0 ) list.pop( uids[ uid ] ); 
					events.set( name, list ); return list.length;
				}
				this.trigger = function( name, data ) {
					if ( events.get_length( name ) == 0 || cs.not( name, '-string' ) ) return {};
					var list = events.get( name ), event = new cs.Event( name, data );
					for ( var i = 0; i < list.length; i++ ) {
						var handler = list[ i ].fn; if ( cs.not( handler, '-function' ) ) continue;
						var returnValue = handler.call( this, event ); event.handlers_fired++;
						if ( returnValue === NO || event.isPropagationStopped === YES ) break;
					}; return event;
				}
			}
		};
		jQuery.each( Constructors, function( T ) { this.native = YES; this.prototype.csObjectType = T } )
		
		function add( Ext, Constructor, Deps ) {
			if ( cs.not( Ext, 'string' ) || cs.not( Constructor, '+function' ) ) return NO;
			Constructor.csObjectType = 'Ext_Constructor'; Constructor.prototype.csObjectType = Ext;
			if ( cs.not( Deps, '+array' ) ) var deps = [];
			Constructors[ Ext ] = Constructor; Dependencies[ Ext ] = Deps; return YES;
		}
		function init_dependencies( Obj, Ext ) {
			if ( cs.not( Obj, '+object' ) || cs.not( Ext, 'string' ) ) return NO;
			var Deps = Dependencies[ Ext ]; if ( cs.not( Deps, '+array' ) ) return NO;
			for ( var i = 0; i < Deps.length; i++ ) { var Dep = Deps[ i ], Name = Dep.toLowerCase();
				if ( cs.not( Dep, 'string' ) || !Constructors[ Dep ] || cs.is( Obj[ Name ], Dep ) ) continue;
				Obj[ Name ] = new Constructors[ Dep ]( Obj );
			}; return YES;
		}
		function list( native ) {
			var ret = []; for ( var i in Dependencies ) {
				if ( !hasOwn( Dependencies, i ) ) continue;
				if ( native && !Constructors[ i ].native ) continue; ret.push( i );
			}; return $A( ret );
		}
		function remove( Ext ) {
			if ( cs.not( Ext, 'string' ) ) return NO; delete Constructors[ Ext ];  delete Dependencies[ Ext ]; return YES;
		}
		function replace( Ext, Constructor, Deps ) {
			var old = [ Ext, this.Constructors[ Ext ], this.Dependencies[ Ext ] ], success;
			remove( Ext ); success = add( Ext, Constructor, Deps );
			if ( success ) return YES; else add.apply( this, old ); return NO;
		}
		function extend( Obj, Extlist ) {
			if ( cs.not( Obj, '+object' ) ) return {};
			if ( cs.not( Extlist, '+array' ) ) return Obj;
			Extlist = $A( Extlist ); var length = Extlist.length, Ext;
			while ( length-- ) { Ext = Extlist.shift();
				if ( !Constructors[ Ext ] || cs.not ( Dependencies[ Ext ], '+array' ) ) continue;
				Obj[ Ext.toLowerCase() ] = construct( Ext, Obj );
			}; return Obj;
		}
		function construct( Ext, Obj ) { return new Constructors[ Ext ]( Obj ) }
		
		return {
			init_dependencies : init_dependencies, list : list, add : add, remove : remove, replace : replace,
			extend : extend, construct : construct
		}
	} )( this );
	this.extend = function( obj ) {
		if ( this.is( obj, 'string' ) ) obj = { name : obj };
		if ( this.not( obj, '+object|boolean' ) ) return NO; var args = $A(arguments );
		if ( this.is( args[ 1 ], 'string' ) ) {
			if ( args[ 1 ] === 'all' ) args[ 1 ] = this.Extensions.list().join( ',' );
			if ( args[ 1 ] === 'native' ) args [ 1 ] = this.Extensions.list( YES ).join( ',' );
			var opts = args[ 1 ].split( /\,/ );
			obj = this.Extensions.extend( obj, opts ); return obj;
		} else if ( obj === YES ) return jQuery.extend( YES, arguments[ 1 ], arguments[ 2 ] );
		else return jQuery.extend( YES, this, obj );
	}
	function extend_natives( cs ) {
		var px_exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
		jQuery.extend( HTMLElement.prototype, {
			abs : function( style ) {
				var get_style = $F( this, function( prop ) {
					var val = '';
					// Compliant browsers
					if ( document.defaultView && document.defaultView ) val = document.defaultView.getComputedStyle( this, '' ).getPropertyValue( prop );
					// Buggy IE
					else if ( this.currentStyle ) { style = style.toCamelCase(); val = this.currentStyle[ prop ] }
					// Last resort
					else val = this.style[ prop ];
					// Convert pixel to num & return
					if ( !px_exclude.test( prop ) && /px$/.test( val ) ) val = val.toInt(); return val;
				} ), i, ret = undefined;
				// Multiple props
				if ( cs.is( style, 'array') ) {
					ret = []; for ( i in style ) { ret[ i ] = get_style.call( self, style[ i ] ) }
				// Single prop
				} else if ( cs.is( style, 'string' ) ) ret = get_style.call( self, style ); return ret;
			},
			remove : function() { var parent = this.parentNode || el.parent; parent.removeChild( this ); },
			html : function( html ) {
				if ( cs.is( this, 'input' ) || cs.is( this, 'textarea' ) ) { return this.val( html ) }
				return $( this ).html( html )
			},
			css : function( style ) {
				var i = 0, type = cs.type( style ),
				set = $F( this, function( prop, val ) {
						if ( !isNaN( val ) && !px_exclude.test( val ) ) val += 'px'; // Convert a num to a pixel
						this.style[ prop.toCamelCase() ] = val;
				} ); // Generic Setter
				// Delete  props
				if ( type == 'array' ) for ( ; i < type.length; i++ ) set( style[ i ], '' );
				// Set multiple props
				else if ( type == 'object' ) for ( var i in style ) set( i, style[ i ] );
				// Set single
				else if ( type == 'string'  && arguments[ 1 ] ) set( style, arguments[ 1 ] );
				// Get single( use .abs directly to get multiple )
				else if ( type == 'string' ) return this.abs( style ); return this;
			},
			colors : function() {
				var ret = {
					background : this.css( 'background-color' ), text : this.css( 'color' ),
					fill : this.css( 'fill' ), flood : this.css( 'flood-color' ),
					lighting : this.css( 'lighting-color' ), outline : this.css( 'outline-color' ),
					stop : this.css( 'stop-color' )
				};
				if ( this.css( '-webkit-text-stroke-color' ) != '' ) { // Test for webkit
					ret.textStroke = this.css( '-webkit-text-stroke-color' ); ret.textFill = this.css( '-webkit-text-fill-color' );
					ret.columnRule = this.css( '-webkit-column-rule-color' );
				};
				for ( var i in ret ) ret[ i ] = cs.colors.css( ret[ i ] );
				return ret;
			},
			attr : function( attr ) {
				var t = cs.type( attr ); if ( t != 'string' && t != 'object' && t != 'array' ) return NO;

				if ( t == 'array' ) for ( var i in attr ) this.removeAttribute( attr[ i ] ); // remove
				else if ( t == 'object' ) for ( var i in attr ) this.setAttribute( i, attr[ i ] ); // add
				else if ( t == 'string'  && cs.is( arguments[ 1 ], 'string' ) ) this.setAttribute( attr, arguments[ 1 ] ); // add
				else if ( t == 'string' ) return this.getAttribute( attr );
				else return NO; return this;
			},
			makeFrontAndCenter : function() {
				if ( !/absolute/.test( this.abs('position') ) ) this.style.position = 'absolute';
				if ( this.parentNode == document.body || !/absolute|relative|fixed/.test( this.parentNode.abs('position') ) ) {
					var top = document.body.scrollTop, left = document.body.scrollLeft;
					var height = window.innerHeight, width = window.innerWidth;

					var w = ( width - this.offsetWidth ) / 2, h = ( height - this.offsetHeight ) / 2;
					var x = w + left, y = h + top;

					this.css( { left : x, top : y } ); return this;
				}
			},
			translateIntoView : function( x, y, fix ) {
				if ( fix === YES ) this.style.position = 'fixed';
				else if ( this.parentNode != document.body || !/absolute|relative|fixed/.test( this.parentNode.abs('position') ) ) {
					if ( !/absolute/.test( this.abs('position') ) ) this.style.position = 'absolute';
					x += document.body.scrollLeft, y += document.body.scrollTop;
				}
				this.css( { left : x, top : y } ); return this;
			},
			liesWithinBounds : function() {
				if ( cs.is( arguments[ 0 ], 'clientrect' ) ) var d2 = arguments[ 0 ];
				else if ( arguments[ 0 ].nodeType == 1 ) var d2 = arguments[ 0 ].getBoundingClientRect(); else return NO;
				var d1 = this.getBoundingClientRect(), ret = NO;

				if ( d1.left >= d2.left && d1.left <= d2.right ) ret = YES;
				else if ( d1.right >= d2.left && d1.right <= d2.right ) ret = YES;

				if ( d1.top >= d2.top && d1.top <= d2.bottom && ret === YES  ) ret = YES;
				else if ( d1.bottom >= d2.top && d1.bottom <= d2.bottom && ret === YES ) ret = YES;
				else ret = NO; return ret;
			}
		});
		jQuery.extend( HTMLInputElement.prototype, {
			val : function( value ) { return $( this ).val( value ) }
		} )

		jQuery.extend( HTMLDivElement.prototype, {
			fillWindow : function() {
				var d = this.bounds(), width = window.innerWidth - d.border.x - d.padding.x, height = window.innerHeight - d.border.y  - d.padding.y;
				var left = document.body.scrollLeft - d.margin.l, top = document.body.scrollTop - d.margin.t, self = this;

				this.fullscreen_properties = {
					left : self.abs('left'), top : self.abs('top'), width : self.abs('width'),
					height : self.abs('height'), position : self.abs('position')
				}; this.fullscreen = YES;

				this.css( { left : left, top : top, width : width, height : height } )
				document.fullScreenElement = self;
			},
			unfillWindow : function() {
				if ( this.fullscreen === NO || !this.fullscreen_properties ) return NO;
				var p = this.fullscreen_properties;
				this.css({
					width : p.width, height : p.height, left : p.left, top : p.top, position : p.position
				})
				delete document.fullScreenElement; delete this.fullscreen_properties; this.fullscreen = NO;
			}
		});
		jQuery.extend( Image.prototype, {
			split : function( animate ) {
				var url = this.src, parent = cs.m( '<div />' ), children = [ cs.m( '<div />' ), cs.m( '<div />' ) ];
				var tmp = this.abs( [ 'margin-top', 'margin-right', 'margin-bottom', 'margin-left' ] );
				var margin = ( '%t %r %b %l' ).insert( tmp, [ 't', 'r', 'b', 'l' ] );
				tmp = this.abs( [ 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' ] );
				var padding = ( '%t %r %b %l' ).insert( tmp, [ 't', 'r', 'b', 'l' ] );

				var css = {
					width : this.abs( 'width' ), height : this.abs( 'height' ), position : this.abs( 'position' ),
					margin : margin, left : this.abs( 'left' ), top : this.abs( 'top' ), right : this.abs( 'right' ),
					bottom : this.abs( 'bottom' ), padding : padding, overflow : 'hidden'
				 }; parent.css( css );
				jQuery.each( children, function() {
					this.css( {
						position : 'relative', 'background-image' : 'url(' + url + ')', 'width' : '100%', height : '50%'
					 });
					parent.appendChild( this );
				}); children[ 1 ].css( 'background-position-y', '100%' )
				this.parentNode.appendChild( parent ); this.remove();
				if ( animate !== NO ) { var c1 = children[ 0 ], c2 = children[ 1 ];
					$(c1).animate( {
						top : '-%xpx'.insert( c1.abs( 'height' ).replace( /px$/, '' ) + 20, 'x' )
					}, 700, jQuery.easing.def );
					$(c2).animate( {
						top : '+=%xpx'.insert( parent.offsetHeight/2 + 20, 'x' )
					}, 700, jQuery.easing.def, function() { parent.remove() } );
				}
				return parent;
			}
		});

		var	toInt = function( radix ) { radix = radix || 10; return parseInt( this, radix ) },
			toFloat = function() { return parseFloat( this ) },
			toJSON = function() { return this.valueOf() };

		jQuery.extend( String.prototype, {
			trim : function() { return this.replace( /^\s+|\s+$/g, '' ) },
			contains : function( str ) { if ( this.indexOf( str ) >= 0 ) return YES; return NO },
			insert : function( rep, target ) {
				var t1 = cs.type( rep ), t2 = cs.type( target );
				if ( ( t1 == 'string' || t1 == 'number' ) && ( t2 == 'string' || t1 == 'number' ) ) {
					return this.replace( new RegExp( '%' + target, 'g' ), rep );
				} else if ( t1 == 'array' && ( cs.is( rep, 'string', YES ) ) && t2 == 'array' && cs.is( target, 'string', YES ) ) {
					var ret = this, length = target.length; if ( length != target.length ) length = Math.min( rep.length, length );
					for ( var i = 0; i < length; i++ ) ret = ret.replace( new RegExp( '%' + target[ i ], 'g' ), rep[ i ] );
					return ret;
				} else return this;
			},
			toTitleCase : function() {
				var p = this.trim().split( /\s/ );
				for ( var i = 0, l = p.length; i < l; i++ ) { var s = p[ i ];
					p[ i ] = s.substring( 0, 1 ).toUpperCase() + s.substring( 1 );
				}; return p.join( ' ' );
			},
			toCamelCase : function() {
				var p = this.trim().split( /\b|_/ );
				for ( var i = 0, l = p.length; i < l; i++ ) { var s = p[ i ];
					if ( i == 0 ) continue; if ( /^[\s\-_]/.test( s ) ) s = '';
					p[ i ] = s.substring( 0, 1 ).toUpperCase() + s.substring( 1 );
				}; return p.join( '' );	
			},
			toJSON : function() {
				var specials = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' },
					escapedString = this.gsub( /[\x00-\x1f\\]/, function( match ) {
					var character = specials[ match[ 0 ] ];
					return character ? character : '\\u00' + match[ 0 ].charCodeAt().toString( 16 );
					});
				return '\"' + escapedString.replace( /"/, '\\"' ) + '\"';
			},
			toInt : toInt, toFloat : toFloat, toArray : function( split ) {
				if ( split ) return this.split( '' ); else return this.split();
			},
			RegExpEscape : function() { return this.replace( /([.*+?^=!:${}()|[\]\/\\])/g, '\\$1' ) },
			stripTags :function() { return this.replace( /<\/?[^>]+>/gi, '' ) },
			stripScripts : function() { return this.replace( new RegExp( ScriptFragment, 'img' ), '' ) },
			extractScripts : function() {
			    var matchAll = new RegExp( ScriptFragment, 'img' ), matchOne = new RegExp( ScriptFragment, 'im' );
				return jQuery.map( this.match( matchAll ) || [], function( scriptTag ) {
			      return ( scriptTag.match( matchOne ) || [ '', '' ] )[ 1 ];
			    });
			},
			evalScripts : function() {
				return jQuery.map( this.extractScripts(), function( script ) { with( window ) { return eval( script ) } } )
			},
			gsub : function( pattern, replacement ) {
		    	var result = '', source = this, match;

		    	if ( cs.is( pattern, 'string' ) ) pattern = pattern.RegExpEscape();
		    	if ( !( pattern.length || pattern.source ) ) {
		      		replacement = replacement( '' );
		      		return replacement + source.split( '' ).join( replacement ) + replacement;
		    	}
		    	while ( source.length > 0 ) {
		      		if ( match = source.match( pattern ) ) {
		        		result += source.slice( 0, match.index ); result += replacement( match ) || '';
		        		source  = source.slice( match.index + match[ 0 ].length );
		      		} else result += source, source = '';
		    	}; return result;
		  	},
			sub : function( pattern, replacement, count ) {
		    	count = cs.is( count, 'undefined' ) ? 1 : count;
		    	return this.gsub( pattern, function( match ) {
		      		if ( --count < 0 ) return match[ 0 ];
		      		return replacement( match );
		    	});
		  	},
			isJSON : function() {
				var str = this; if ( str.blank() ) return NO;
				str = this.replace( /\\./g, '@' ).replace( /"[^"\\\n\r]*"/g, '' );
				return ( /^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/ ).test( str );
			},
			empty : function() { return this == '' },
			blank : function() { return /^\s*$/.test( this ) },
			tester : function( opts ) { var regexp = new RegExp( this, opts ); return regexp.tester() },
			matcher : function( opts ) { var regexp = new RegExp( this, opts ); return regexp.matcher() },
			remove : function( re ) {
				if ( cs.not( re, 'string|regexp' ) ) return this;
				if ( cs.is( re, '-string' ) ) re = new RegExp( re ); return this.replace( re, '' );
			}
		});
		jQuery.extend( Number.prototype, {
			toInt : toInt, toFloat : toFloat, toJSON : toJSON, toArray : function() { return [ this ] },
			toFactorial : function() { return Math.factorial( this ) },
			toRadian : function() { return Math.PI / 180 * this },
			toDegree : function() { return this / Math.PI * 180 },
			permute : function( r ) {
				if ( isNaN( r ) || r < 0 || this < 0 || r > this ) return 0; var f = Math.factorial; return ( f( this ) / f( this - r ) )
			},
			choose : function( r ) {
				if ( isNaN( r ) || r < 0 || this < 0 || r > this ) return 0; var f = Math.factorial; return f( this ) / ( f( r ) * f( this - r ) )
			}
		});
		jQuery.extend( RegExp.prototype, {
			tester : function() { return $F( this, function( str ) { return this.test( str ) } ) },
			matcher : function() { return $F( this, function( str ) { return this.exec( str ) } ) }
		});
		jQuery.extend( Boolean.prototype, { toJSON : toJSON, toArray : function() { return [ this ] } } );
		jQuery.extend( Date.prototype, {
			toJSON : function () {
				var f = Math.pad;
				return this.getUTCFullYear() + '-' + f( this.getUTCMonth() + 1 ) + '-' +
					f( this.getUTCDate() ) + 'T' + f( this.getUTCHours() ) + ':' +
					f( this.getUTCMinutes() ) + ':' + f( this.getUTCSeconds() ) + 'Z';
			},
			toArray : function() { return String( this ).split( ' ' ) },
			getDayString : function() { return this.toArray()[ 0 ] + 'day' },
			getMonthString : function() {
				var months = ( 'January February March April May June July August September October November December' ).split( ' ' );
				return months[ this.getMonth() ];
			}
		});
		jQuery.getJSON = function( url, data, callback, type ) {
			return jQuery.ajax( {
				type: "GET", url: url, data: data, success: callback, dataType: type,
				dataFilter : function( d ) { return json.decode( d ) }
			});
		}
		jQuery.extend( Math, {
			factorial : function( n ) { for ( var ret = 1; n > 0; n-- ) { ret *= n } return ret },
			pad : function( n ) { return ( n < 10 ) ? String( '0' + n ) : n }
		});
	};
	extend_natives( this );
	
	// Constructors
	this.Application = function( App ) {
		if ( cs.not( this, 'Application' ) ) return new this.Application( App );
		if ( cs.not( App, 'object' ) || cs.not( App.name, 'string|number' ) ) return NO;
		this.name = App.name; this.version = ( App.version ) ? App.version : '0.0';
		this.info = cs.is( App.info, 'object' ) ? App.info : {};
		
		cs.extend( this, cs.is( App.implements, 'string' ) ? App.implements : 'all'  );
		this.csObjectType = ( cs.is( App.ObjectType, 'string' ) ) ? App.ObjectType : 'Application';
		this.extend = function( obj ) {
			if ( cs.is( obj, 'string' ) ) return cs.extend( this, obj ); else return jQuery.extend( YES, this, obj );
		};
		if ( cs.is( App.base, 'object' ) ) this.extend( App.base );
		if ( cs.is( App.initialize, 'function' ) ) App.initialize.call( this ); 
		if ( App.declare !== NO ) window[ App.name ] = this;
		Applications.add( this );
	}
	this.Application.prototype.csObjectType = 'Application';
	this.SWF = function( options ) {
		if ( cs.not( options, 'object' ) || cs.not( options.src, 'string' ) ) return NO;
		cs.extend( this, 'Options' );
		this.csObjectType = 'SWF';
		this.options.multi_set( options );
		var obj = cs.m( '<object />' );
		
		var params = options.params, vars = options.vars, props = {};
		if ( cs.is( vars, 'object' ) && cs.is( vars, 'string|number|boolean', YES ) ) {
			var flashVars = [];
			for ( var i in vars ) { if ( !hasOwn( vars, i ) ) continue;
				flashVars.push( i + '=' + encodeURIComponent( vars[ i ] ) );
			}; params.flashVars = flashVars.join( '&' );
		}
		props.width = ( !isNaN( options.width ) ) ? options.width : 400, props.height = ( !isNaN( options.height ) ) ? options.height : 400;
		if ( 'ActiveXObject' in window ) {
			props.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
			params.movie = options.src;
		} else {
			props.type = 'application/x-shockwave-flash'; props.data = options.src;
		}
		for ( var i in props ) { if ( !hasOwn( props, i ) ) continue; obj.attr( i, props[ i ] ); }
		for ( var i in params ) { if ( !hasOwn( params, i ) ) continue;
			var p = cs.m( '<param />' ); p.attr( { name : i, value : params[ i ] } ); obj.appendChild( p );
		}
		this.object = obj;
		this.append = function( el, context ) {
			if ( el.nodeType == 1 ) el.appendChild( this.object );
			else {
				el = cs.r( el, context, 0 ); if ( el.nodeType != 1 ) return NO;
				el.appendChild( this.object );
			}
			this.parent = el; return this;
		}
		this.remove = function() { this.object.remove() }
		this.version = function() {
			if ( 'ActiveXObject' in window ) {
				return new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' ).GetVariable( "$version" ).split( " " )[ 1 ];
			} else {
				return navigator.plugins[ 'Shockwave Flash' ].description.match( /[\d]+\.[\d]+\sr[\d]+$/ )[ 0 ];
			}
		}
		if ( options.append !== NO ) { var p = options.parent;
			p = ( p && p.nodeType === 1 ) ? p : document.body; this.append( p ); this.parent = p;
		}
	}
	this.Periodic = function( fn, interval, imm ) {
		if ( cs.not( fn, 'function' ) ) var interval = fn, tmp = function() {}; else tmp = fn;
		var interval = ( !isNaN( interval ) ) ? interval : 400;

		fn = function() { var proceed = tmp.call( window ); if ( proceed === NO ) this.stop() }
		if ( imm === YES ) { var id = setInterval( fn, interval ), running = YES } else { var id = 0, running = NO }
		
		this.csObjectType = 'Periodic';
		this.fn = fn; this.interval = interval; this.isRunning = running; this.id = id;
		this.running = function( b ) { if ( cs.is( b, 'boolean' ) ) return this.isRunning = b; else return this.isRunning };
		this.stop = function() { clearInterval( this.id ); return this.running( NO ) };
		this.run = function( fn ) {
			if ( cs.is( fn, 'function' ) ) this.fn = fn; else if ( !cs.is( this.fn, 'function' ) ) return NO;
			this.interval = ( !isNaN( this.interval ) ) ? this.interval : 400;
			if ( this.running() ) return this.id; else this.running( YES );
			this.id = setInterval( this.fn, this.interval ); return this.id;
		}
	}
	
	// Events Setup
	this.Event = function( type, data ) {
		if ( cs.not( this.stopPropagation, '-function' ) ) return new this.Event( type, data );
		if ( cs.is( type, '+object' ) ) var data = type, type = '';
		this.type = type; this.timeStamp = Time.now(); this.handlers_fired = 0;
		this.isPropagationStopped = NO; this.isDefaultPrevented = NO;
		cs.Event._extend( this, type ); if ( cs.is( data, '+object' ) ) jQuery.extend( this, data );
	}
	this.Event.prototype = ( function() {
		return {
			stopPropagation : function() { this.isPropagationStopped = YES },
			preventDefault : function() { this.isDefaultPrevented = YES }, csObjectType : 'Event'
		}
	} )();
	this.Event.types = { all : {} };
	this.Event.extend = function( type, data ) {
		if ( cs.not( type, '-string' ) || cs.not( data, '+object' ) ) return NO;
		if ( cs.not( this.types[ type ], '+object' ) ) this.types[ type ] = {};
		jQuery.extend( YES, this.types[ type ], data ); return cs.length( this.types[ type ] );
	}
	this.Event._extend = function( event, type ) {
		if ( cs.not( this.types[ type ], '+object' ) ) return;
		event = jQuery.extend( YES, event, this.types.all ); return jQuery.extend( YES, event, this.types[ type ] );
	}
	
	// Color Setups
	function Color( self, type ) {
		if ( cs.is( self, 'string' ) ) {
			if ( /^rgb|hsb|hex$/.test( self ) ) var type = self, self = [ 0, 0, 0 ];
			else var self = [ 0, 0, 0 ], type = 'rgb';
		} else if ( cs.is( self, '+array' ) ) {
			if ( cs.not( self, 'number', YES ) && ( type == 'hsb' || type == 'rgb' ) ) var self = [ 0, 0, 0 ];
			else if ( cs.not( self, 'string', YES ) && type == 'hex' ) var self = [ '00','00', '00' ];
		} else var self = [ 0, 0, 0 ];
		self = cs.colors.fix( self, type );
		self.type = type; var _type = type; self.csObjectType = 'Color';
		self.clean = function( a ) { var arr = a || this; return $A( arr ) };
		self.rgb = function( c ) {
			if ( cs.is( c, '+array' ) ) return self.set( c, 'rgb' );
			var arr = this.clean();
			if ( this.type == 'rgb' ) return this;
			else if ( this.type == 'hsb' ) return cs.colors.hsb_to_rgb( arr );
			else if ( this.type == 'hex' ) return cs.colors.hex_to_rgb( arr );
		}
		self.hsb = function( c ) {
			if ( cs.is( c, '+array' ) ) return self.set( c, 'hsb' );
			var arr = this.clean();
			if ( this.type == 'hsb' ) return this;
			else if ( this.type == 'rgb' ) return cs.colors.rgb_to_hsb( arr );
			else if ( this.type == 'hex' ) return cs.colors.hex_to_hsb( arr );
		}
		self.hex = function( c ) {
			if ( cs.is( c, '+array' ) ) return self.set( c, 'hex' );
			var arr = this.clean();
			if ( this.type == 'hex' ) return this;
			else if ( this.type == 'hsb' ) return cs.colors.hsb_to_hex( arr );
			else if ( this.type == 'rgb' ) return cs.colors.rgb_to_hex( arr );
		}
		self.css = function( type ) {
			return ( type && type == 'hex' ) ? '#' + this.hex().join( '' ) : 'rgb(' + this.rgb().join( ',' ) + ')';
		}
		self.invert = function() {
			var rgb = this.rgb(); for ( var i = 0; i < rgb.length; i++ ) { this[ i ] = 255 - rgb[ i ] }; return this
		}
		self.set = function( c, type ) {
			var arr = [], c = this.clean( c );
			if ( cs.not( c, '+array' ) || !/^rgb|hsb|hex$/.test( type ) ) return null;

			if ( type == 'rgb' && _type == 'rgb' ) arr = c;
			else if ( type == 'rgb' && _type == 'hsb' ) arr = cs.colors.rgb_to_hsb( c );
			else if ( type == 'rgb' && _type == 'hex' ) arr = cs.colors.rgb_to_hex( c );
			else if ( type == 'hsb' && _type == 'hsb' ) arr = c;
			else if ( type == 'hsb' && _type == 'rgb' ) arr = cs.colors.hsb_to_rgb( c );
			else if ( type == 'hsb' && _type == 'hex' ) arr = cs.colors.hsb_to_hex( c );
			else if ( type == 'hex' && _type == 'hex' ) arr = c;
			else if ( type == 'hex' && _type == 'rgb' ) arr = cs.colors.hex_to_rgb( c );
			else if ( type == 'hex' && _type == 'hsb' ) arr = cs.colors.hex_to_hsb( c );
			else return this;
			
			for ( var i = 0; i < 3; i++ ) self[ i ] = arr[ i ]; return this;
		}
		self.__defineSetter__( 'values', function( a ) { return this.set( a, _type ) } )
		self.__defineGetter__( 'values', function() { return $A( this ) } );
		self.__defineSetter__( 'type', function( t ) {
			var tmp = cs.colors[ _type + '_to_' + t ]( this ), l; if ( !tmp ) return this;
			l = tmp.length; while( l-- ) this[ l ] = tmp [ l ]; _type = t; return $A( this );
		} );
		self.__defineGetter__( 'type', function() { return _type } );
		return self;
	}
	this.color = function( c, type ) { return Color( c, type ) };
	this.colors = ( function( cs ) {
			var colors = {
				aqua : [ 0, 255, 255 ], azure : [ 240, 255, 255 ], beige : [ 245, 245, 220 ], black : [ 0, 0, 0 ],
				blue : [ 0, 0, 255 ], brown : [ 165, 42, 42 ], cyan : [ 0, 255, 255 ], darkblue : [ 0, 0, 139 ],
				darkcyan : [ 0, 139, 139 ], darkgrey : [ 169, 169, 169 ], darkgreen : [ 0, 100, 0 ], darkkhaki : [ 189, 183, 107 ],
				darkmagenta : [ 139, 0, 139 ], darkolivegreen : [ 85, 107, 47 ], darkorange : [ 255, 140, 0 ],
				darkorchid : [ 153, 50, 204 ], darkred : [ 139, 0, 0 ], darksalmon : [ 233, 150, 122 ], darkviolet : [ 148, 0, 211 ],
				fuchsia : [ 255, 0, 255 ], gold : [ 255, 215, 0 ], green : [ 0, 128, 0 ], indigo : [ 75, 0, 130 ],
				khaki : [ 240, 230, 140 ], lightblue : [ 173, 216, 230 ], lightcyan : [ 224, 255, 255 ],
				lightgreen : [ 144, 238, 144 ], lightgrey : [ 211, 211, 211 ], lightpink : [ 255, 182, 193 ],
				lightyellow : [ 255, 255, 224 ], lime : [ 0, 255, 0 ], magenta : [ 255, 0, 255 ], maroon : [ 128, 0, 0 ],
				navy : [ 0, 0, 128 ], olive : [ 128, 128, 0 ], orange : [ 255, 165, 0 ], pink : [ 255, 192, 203 ],
				purple : [ 128, 0, 128 ], violet : [ 128, 0, 128 ], red : [ 255, 0, 0 ], silver : [ 192, 192, 192 ],
				white : [ 255, 255, 255 ], yellow : [ 255, 255, 0 ]
			};
						
			function rgb( c ) { return cs.color( c, 'rgb' ) };
			function hsb( c ) { return cs.color( c, 'hsb' ) };
			function hex( c ) { return cs.color( c, 'hex' ) };
			function css( c ) {
				if ( cs.is( c, 'color|array' ) ) return c;
				if ( cs.not( c, 'string' ) ) return null; c = c.trim(); var res;
				if ( res = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/.exec( c ) ) {
					return cs.color( [ res[ 1 ].toInt(), res[ 2 ].toInt(), res[ 3 ].toInt() ], 'rgb' ) }
				else if ( res = /^\#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/.exec( c ) ) {
					res.shift(); jQuery.each( res, function( i ) { res[ i ]  = res[ i ].toInt( 16 ) } )
					return cs.color( res, 'rgb' ) }
				else if ( res = /^\#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/.exec( c ) ) {
					res.shift(); jQuery.each( res, function( i ) { res[ i ]  = ( res[ i ] + res[ i ] ).toInt( 16 ) } )
					return cs.color( res, 'rgb' ) }
				else return cs.color( colors[ c.trim().toLowerCase() ], 'rgb' );
			};
			function rgb_to_hsb( rgb ) {
				if ( cs.not( rgb, '+array' ) || cs.not( rgb, 'number', YES ) || rgb.length < 3 ) return NO;
				var red = rgb[ 0 ], green = rgb[ 1 ], blue = rgb[ 2 ], hue, saturation, brightness,
				max = cs.max( rgb ), min = cs.min( rgb ), delta = max - min;
				saturation = ( max == 0 ) ? 0 : 100 * delta / max, brightness = max / 2.55;
				if ( delta == 0  ) hue = 0; else { 
					if ( red == max ) hue = ( green - blue ) / delta * 60;
					else if ( green == max ) hue = ( blue - red ) / delta * 60 + 120;
					else if ( blue == max ) hue = ( red - green ) / delta * 60 + 240;
				}
				return this.fix( [ Math.round( hue ), Math.round( saturation ), Math.round( brightness ) ], 'hsb' );
			};
			function rgb_to_hex( rgb ) {
				if ( cs.not( rgb, '+array' ) || cs.not( rgb, 'number', YES ) || rgb.length < 3 ) return NO;

				var red = rgb[ 0 ].toString( 16 ), green = rgb[ 1 ].toString( 16 ), blue = rgb[ 2 ].toString( 16 );
				function pad( s ) { return ( s.length == 2 ) ? s : '0' + s };
				return [ pad( red ), pad( green ), pad( blue ) ];
			};
			function hsb_to_rgb( hsb ) {
				if ( cs.not( hsb, '+array' ) || cs.not( hsb, 'number', YES ) || hsb.length < 3 ) return NO;

				var h = hsb[ 0 ], s = hsb[ 1 ], b = hsb[ 2 ], ret = NO;
				var br = Math.round( b / 100 * 255 );
				if ( s == 0 ) ret = [ br, br, br ];
				else {
					var hue = h % 360, f = hue % 60;
					var p = Math.round( ( b * ( 100 - s ) ) / 10000 * 255 );
					var q = Math.round( ( b * ( 6000 - s * f ) ) / 600000 * 255 );
					var t = Math.round( ( b * ( 6000 - s * ( 60 - f ) ) ) / 600000 * 255 );
					switch ( Math.floor( hue / 60 ) ) {
						case 0: ret = [ br, t, p ]; break; case 1: ret = [ q, br, p ]; break;
						case 2: ret = [ p, br, t ]; break; case 3: ret = [ p, q, br ]; break;
						case 4: ret = [ t, p, br ]; break; case 5: ret = [ br, p, q ]; break;
					}
				} return this.fix( ret, 'rgb' );
			};
			function hsb_to_hex( hsb ) {
				if ( cs.not( hsb, '+array' ) || cs.not( hsb, 'number', YES ) || hsb.length < 3 ) return NO;
				var rgb = this.hsb_to_rgb( hsb ); return this.rgb_to_hex( rgb );
			};
			function hex_to_rgb( hex ) {
				if ( cs.not( hex, '+array' ) || cs.not( hex, 'string', YES ) || hex.length < 3 ) return NO;
				return this.fix( [ hex[ 0 ].toInt( 16 ), hex[ 1 ].toInt( 16 ), hex[ 2 ].toInt( 16 ) ], 'rgb' );
			};
			function hex_to_hsb( hex ) {
				if ( cs.not( hex, '+array' ) || cs.not( hex, 'string', YES ) || hex.length < 3 ) return NO;
				var rgb = this.hex_to_rgb( hex ); return this.fix( this.rgb_to_hsb( rgb ), 'hsb' );
			};
			function fix( color, type ) {
				var color = $A( color );
				if ( cs.not( color, 'number|string', YES ) || color.length < 3 ) var color = [ 0, 0, 0 ];
				if ( type === 'hsb' ) var constraints = [ 359, 100, 100, 0, 0, 0 ];
				else var constraints = [ 255, 255, 255, 0, 0, 0 ];
				if ( type == 'hex' ) var color = this.hex_to_rgb( color );
				for ( var i = 0; i < color.length; i++ ) {
					color[ i ] = Math.min( Math.max( color[ i ], constraints[ i + 3 ] ), constraints[ i ] );
				};
				if ( type == 'hex' ) return this.rgb_to_hex( color ); else return color;	
			};

			function get_color( el, attr ) {
				var c;
				do {
					c = jQuery.curCSS( el, attr );
					if ( c != '' && c != 'transparent' || jQuery.nodeName( el, 'html' ) ) break;  attr = "backgroundColor";
				} while ( el = elem.parentNode ); return cs.colors.css( c );
			};
			
			var s = [ 'backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor' ]
			jQuery.each( s, function( i, attr ){
				jQuery.fx.step[ attr ] = function( fx ) {
					if ( fx.state == 0 ) { fx.start = get_color( fx.elem, attr ).clean(); fx.end = cs.colors.css( fx.end ).clean(); }

					fx.elem.style[ attr ] = 'rgb(' + [
						Math.max( Math.min( ( ( fx.pos * ( fx.end[ 0 ] - fx.start[ 0 ] ) ) + fx.start[ 0 ] ).toInt(), 255 ), 0 ),
						Math.max( Math.min( ( ( fx.pos * ( fx.end[ 1 ] - fx.start[ 1 ] ) ) + fx.start[ 1 ] ).toInt(), 255 ), 0 ),
						Math.max( Math.min( ( ( fx.pos * ( fx.end[ 2 ] - fx.start[ 2 ] ) ) + fx.start[ 2 ] ).toInt(), 255 ), 0 )
					].join( ',' ) + ')';
				}
			});
			return  {
				rgb : rgb, hsb : hsb, hex : hex, css : css, fix : fix,
				rgb_to_hsb : rgb_to_hsb, rgb_to_hex : rgb_to_hex, hsb_to_rgb : hsb_to_rgb,
				hsb_to_hex : hsb_to_hex, hex_to_rgb : hex_to_rgb, hex_to_hsb : hex_to_hsb
			}
	} )( this );

	// DOM Methods
	this.make = this.m = function( opts ) {
		var append = YES, args = $A( arguments );
		if ( cs.is( opts, 'string' ) ) {
			var el = this.find( opts ); if ( el.nodeType != 1 ) return NO;
			if ( args[ 1 ] && args[ 1 ].nodeType === 1 ) {
					var parent = args[ 1 ], append = YES; if ( cs.is( args[ 2 ], 'object' ) ) el.css( args[ 2 ] );
			} else if ( cs.is( args[ 1 ], 'object' ) ) {
				el.css( args[ 1 ] ); var append = NO, parent = NO;
			} else var append = NO, parent = NO;
		} else if ( cs.is( opts, 'object' ) ) {
			opts.type = ( cs.is( opts.type, 'string' ) ) ? opts.type : 'DIV'; var el = document.createElement( opts.type );
			if ( el.nodeType != 1 ) return NO;
			if ( cs.is( opts.className, 'string' ) ) $( el ).addClass( opts.className );
			if ( cs.is( opts.id, 'string' ) ) el.id = opts.id; if ( cs.is( opts.style, 'object' ) ) el.css( opts.style );
			if ( cs.is( opts.attr, 'object' ) ) el.attr( opts.attr );
			if ( cs.is( opts.val, 'string|number|boolean' ) && ( cs.is( el, 'input' ) || cs.is( el, 'textarea' ) ) ) el.val( opts.val );
			if ( cs.is( opts.html, 'string|number|boolean' ) ) el.html( opts.html );
			var append = ( opts.append === NO ) ? NO : YES, parent = opts.parent;
		} else return NO;
		
		parent = ( parent && parent.nodeType === 1 ) ? parent : document.body;
		if ( append === NO ) { /* Nothing */ } else { parent.appendChild( el ) }; return el;
	};
	this.find = this.r = function( selector, context, num )  {
		var num = !isNaN( num ) ? num : !isNaN( context ) ? context : undefined,
		context = isNaN( context ) ? context : undefined, ret = $( selector, context ), found = ret.get();
		return found.length == 1 ? ret[ 0 ] : !isNaN( num ) ? ret[ num ] : found;
	}
	this.title = function( str ) {
		if ( str === YES ) str = cs.options.get( 'title' );
		if ( cs.is( str, 'string' ) ) { document.title = str; return cs }
		else return document.title;
	}

	// Cookie Setter/Getters
	this.cookie = ( function( cs ) {
		return {
			get : function( name ) {
				if ( cs.not( name, 'string|number' ) ) return document.cookie;
				var re = new RegExp( name + "=[^;]+", "i" ); var ret = document.cookie.match( re );
	 			ret = ( ret ) ? ret[ 0 ].split( "=" )[ 1 ] : NO; return ( ret && decodeURIComponent ) ? decodeURIComponent( ret ) : ret;
			},
			set : function( name, value, seconds ) {
				value = ( encodeURIComponent ) ? encodeURIComponent( value ) : value;
				if ( !isNaN( seconds ) ) {
					var d = new Date(); d.setTime( d.getTime() + seconds.toInt() );
					document.cookie = name + "=" + value + "; path=/; expires=" + d.toGMTString();
				} else document.cookie = name + "=" + value; return document.cookie;
			},
			unset : function( name ) {
				if ( cs.not( name, 'string' ) ) return NO;
				document.cookie = name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT;'; return document.cookie;
			}
		}
	} )( this );
	
	// Randomness
	this.$int = function( min, max ) {
		if ( min === undefined ) var min = 0, max = 1; if ( max === undefined ) var max = min + 1;
		return Math.floor( this.$float( min, max ) );
	};
	this.$float = function( min, max ) { return Math.random() * ( max - min + 1 ) + min };
	this.$letter = function() { 
		var l = 'abcdefghijklmnopqrstuvwxyz'; var x = this.$int( 1, 26 ), letter = l.substring( x - 1, x )
		return ( cs.$int( 0, 1 ) == 1 ) ? letter : letter.toUpperCase();
	}
	this.$word = function( min, max ) {
		var l = this.$int( min, max ); for ( var i = 0, ret = ''; i < l; i++ ) ret += this.$letter(); return ret; 
	}
	
	// Array/Object Helpers
	this.each = function( obj, fn, args ) {
		if ( cs.is( fn, 'string' ) && cs.not( obj, 'array' ) ) {
			for ( var i in obj ) { if ( !hasOwn( obj, i ) ) continue;
				if ( cs.not( obj[ i ][ fn ], 'function' ) ) continue;
				if ( obj[ i ][ fn ].apply( obj[ i ], args ) );
			}
		} else return jQuery.each( obj, fn, args );
	}
	this.max = function( arr ) {
		var ret = arr[ 0 ]; jQuery.each( arr, function() { if ( !isNaN( this ) &&  this > ret ) ret = this } ); return ret;
	};
	this.min = function( arr ) {
		var ret = arr[ 0 ]; jQuery.each( arr, function() { if ( !isNaN( this ) &&  this < ret ) ret = this } ); return ret;
	};
	this.equals = function( arr1, arr2 ) {
		if ( arr1.length != arr2.length ) return NO; var ret = YES;
		for ( var i = 0; i < arr1.length; i++ ) if ( arr1[ i ] !== arr2[ i ] ) { ret = NO; break }; return ret;
	}
	this.length = function( obj ) {
		if ( cs.is( obj, 'null|undefined' ) ) return 0;
		if ( obj.length && !isNaN( obj.length ) && cs.not( obj, 'object' ) ) return obj.length;
		if ( cs.is( obj, '+object' ) || cs.is( obj, '-object' ) ) { var length = 0;
			for ( var i in obj ) { if ( !hasOwn( obj, i ) || i == 'length' || i == 'count' ) continue; length++ };
			return length;
		}
		if ( cs.is( obj, 'number' ) ) return obj.toString().length; if ( cs.is( obj, 'boolean' ) ) return 1;
	}
	this.filter = function( obj, filter ) {
		// Check obj is array/object + set ret accordingly;
		if ( this.not( obj, '-object' ) ) return obj; var ret = this.is( obj, '+object' ) ? {} : [];
		// Figure out if filtering by a type or a custom filter function
		var f = cs.is( filter, '+function' ), s = cs.is( filter, '+string' );
		// Do the filtration
		for ( var i in obj ) { if ( !hasOwn( obj, i ) ) continue;
			// If the property type passes the filter it is retained. Otherwise, it is discarded;
			if ( s ) if ( this.is( obj[ i ], filter ) ) ret[ i ] = obj[ i ];
			// Same deal as above. The filter is called as follows: function filter( property_key, property_value ) {}
			// with 'this' set to the object to be filtered( @var obj );
			if ( f ) if ( filter.call( obj, i, obj[ i ] ) !== NO ) ret[ i ] = obj[ i ];
		}; return ret;
	}
	this.filter_out = function( obj, filter ) {
		var excl = this.filter( obj, filter ), ret = this.is( excl, '+object' ) ? {} : [];
		for ( var i in obj ) { if ( !hasOwn( obj, i ) ) continue;
			if ( excl[ i ] === undefined || excl[ i ] === null ) ret[ i ] = obj[ i ]; 
		}; return ret;
	}
	
	// JSON Module( private and public copy, for security purposes )
	var json = ( function( cs ) {
		return {
			encode : function( obj ) {
				if ( obj.nodeType == 1  ) return; var type = cs.type( obj, YES );
				switch ( type ) {
					case 'undefined': case 'function': case 'unknown': return;
					case 'boolean': return obj.toString();
					case 'number': return isFinite( obj ) ? obj.toString() : 'null';
					case 'null': return 'null';
			    }

				if ( cs.is( obj.toJSON, '+function' ) ) return obj.toJSON();
				var stringify = ( window.JSON ) ? window.JSON.stringify : null, ret = [];
				if ( cs.is( stringify, 'function' ) ) return stringify( cs.filter_out( obj, '+function' ) );

				for ( var property in obj ) {
					var value = json.encode( obj[ property ] );
					if ( cs.not( value, 'undefined' ) ) ret.push( property.toJSON() + ': ' + value );
			    }
			    return '{' + ret.join( ', ' ) + '}';
			},
			decode : function( str ) {
				var json = str.sub( JSONFilter, '#{1}' );
				try { if ( json.isJSON() ) return eval( '(' + json + ')' ) } catch ( e ) { }
				throw new SyntaxError( 'Badly formed JSON string: ' + str );
			}
		}
	} )( this );
	this.json = json;
	
	// Hash Algorithms( private and public copy, for security purposes )
	var sha1 = ( function( cs ) {
		//	The following methods is a javascript implementation of the Secure Hash Algorithm( SHA-1 )
		//	that has been modified to work with core_services.
		//	Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
		//	See http://pajhome.org.uk/crypt/ for details.
		return function( str, unicode, b64 ) {
				if ( cs.not( str, 'string|number' ) && cs.not( str.toString, '+function' ) ) return NO;
				str = str.toString(); var hexcase = 0, b64pad  = "", chrsz = ( unicode === YES ) ? 16 : 8;
				function hex_sha1( s ) { return binb2hex( core_sha1( str2binb( s ), s.length * chrsz ) ) }
				function b64_sha1( s ) { return binb2b64( core_sha1( str2binb( s ), s.length * chrsz ) ) }
				function core_sha1( x, len ) {
					x[ len >> 5 ] |= 0x80 << ( 24 - len % 32 );
					x[ ( ( len + 64 >> 9 ) << 4 ) + 15 ] = len;
					var w = Array( 80 ), a =  1732584193, b = -271733879, c = -1732584194, d =  271733878, e = -1009589776;

					for ( var i = 0; i < x.length; i += 16 ) {
				    	var olda = a, oldb = b, oldc = c, oldd = d, olde = e;
						for( var j = 0; j < 80; j++) {
				      		if ( j < 16 ) w[ j ] = x[ i + j ];
				      		else w[ j ] = rol( w[ j - 3 ] ^ w[ j - 8 ] ^ w[ j - 14 ] ^ w[ j - 16 ], 1 );
				      		var t = safe_add( safe_add( rol( a, 5 ), sha1_ft( j, b, c, d ) ), safe_add( safe_add( e, w[ j ] ), sha1_kt( j ) ) );
				      		e = d, d = c, c = rol( b, 30 ), b = a,a = t;
						}
				    	a = safe_add( a, olda ), b = safe_add( b, oldb ),c = safe_add( c, oldc) , d = safe_add( d, oldd ), e = safe_add( e, olde );
						}; return Array( a, b, c, d, e );
				}
				function sha1_ft( t, b, c, d ) {
				  	if ( t < 20 ) return ( b & c ) | ( ( ~b ) & d ); if ( t < 40 ) return b ^ c ^ d; if ( t < 60 ) return ( b & c ) | ( b & d ) | ( c & d );
				  	return b ^ c ^ d;
				}
				function sha1_kt( t ) { return ( t < 20 ) ?  1518500249 : ( t < 40 ) ?  1859775393 : ( t < 60 ) ? -1894007588 : -899497514 }
				function core_hmac_sha1( key, data ) {
				  	var bkey = str2binb( key );
				  	if ( bkey.length > 16 ) bkey = core_sha1( bkey, key.length * chrsz );

				  	var ipad = Array( 16 ), opad = Array( 16 );
				  	for ( var i = 0; i < 16; i++ ) { ipad[i] = bkey[i] ^ 0x36363636, opad[i] = bkey[i] ^ 0x5C5C5C5C }

				  	var hash = core_sha1( ipad.concat( str2binb( data ) ), 512 + data.length * chrsz );
				  	return core_sha1( opad.concat( hash ), 512 + 160 );
				}
				function safe_add( x, y ) {
				  	var lsw = ( x & 0xFFFF ) + ( y & 0xFFFF ), msw = ( x >> 16 ) + ( y >> 16 ) + ( lsw >> 16 );
				  	return ( msw << 16 ) | ( lsw & 0xFFFF );
				}
				function rol( num, cnt ) { return ( num << cnt ) | ( num >>> ( 32 - cnt ) ) }
				function str2binb( str ) {
					var bin = Array(), mask = ( 1 << chrsz ) - 1;
					for ( var i = 0; i < str.length * chrsz; i += chrsz ) bin[ i >> 5 ] |= ( str.charCodeAt( i / chrsz ) & mask ) << ( 32 - chrsz - i % 32 );
					return bin;
				}
				function binb2str( bin ) {
				  	var str = "", mask = (1 << chrsz) - 1;
				  	for ( var i = 0; i < bin.length * 32; i += chrsz ) str += String.fromCharCode( ( bin[ i >> 5 ] >>> ( 32 - chrsz - i % 32 ) ) & mask );
				  	return str;
				}
				function binb2hex( binarray ) {
				  	var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef", str = "";
				  	for ( var i = 0; i < binarray.length * 4; i++) str += hex_tab.charAt( ( binarray[ i >> 2 ] >> ( ( 3 - i % 4 ) * 8 + 4 ) ) & 0xF ) + hex_tab.charAt( ( binarray[ i >> 2 ] >> ( ( 3 - i % 4 ) * 8 ) ) & 0xF );
				  	return str;
				}
				function binb2b64( binarray ) {
				  	var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", str = "";
				  	for ( var i = 0; i < binarray.length * 4; i += 3 ) {
				    	var triplet = ( ( ( binarray[ i >> 2 ] >> 8 * ( 3 -  i % 4 ) ) & 0xFF ) << 16 ) | ( ( ( binarray[ i + 1 >> 2 ] >> 8 * ( 3 - ( i + 1 ) % 4 ) ) & 0xFF ) << 8 ) |  ( ( binarray[ i + 2 >> 2 ] >> 8 * ( 3 - ( i + 2 ) % 4 ) ) & 0xFF);
				    	for ( var j = 0; j < 4; j++ ) {
				      		if ( i * 8 + j * 6 > binarray.length * 32 ) str += b64pad;
				      		else str += tab.charAt( ( triplet >> 6 * ( 3 - j ) ) & 0x3F );
				    	}
				  	}; return str;
				}
				if ( b64 === YES ) return b64_sha1( str ); else return hex_sha1( str );
			},
	} )( this );
	this.sha1 = sha1;
	
	// Debug Scaffolding Methods
	this.scaffolding = ( function( cs ) {
		 function $dummy() {
			var lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' +
				'Vestibulum quis metus quis nibh sagittis dapibus. Sed suscipit, ante at varius porttitor, ' +
				'nibh neque placerat nisl, eget euismod tortor justo ut metus. Praesent mattis, ' +
				'odio at bibendum molestie, massa tortor lobortis leo, scelerisque laoreet turpis felis vel orci. ' +
				'Proin enim libero, facilisis et, suscipit vitae, dapibus eu, ante. Nam volutpat odio nec turpis.' +
				'Aliquam mollis metus ut dui.';

			return cs.m( {
				html : lorem.substring( 0, cs.$int( 26, lorem.length ) ), className : 'csDummyDiv',
				style : {
					position : 'absolute', 'font-family' : 'Geneva',
					left : cs.$int( 10, window.innerWidth - 200 ),
					top : cs.$int( 10, window.innerHeight - 200 ),
					width : cs.$int( 120, 300 ), 
					border : '1px solid white', 'background-color' : 'black', color : 'white', padding : 10,
					'padding-bottom' : 40
				}
			});
		};
		function $dummies( min, max ) {
			var ret = [], n = cs.$int( min, max ), i = 0; for ( ; i <= n; i++ ) ret.push( this.$dummy() ); return ret;
		};
		function $object( obj ) {
			var ret = {}, num = cs.$int( 1, 10 );
			while ( num-- ) { ret[ cs.$word( 3, 6 ) ] = cs.$word( 2, 10 ); }
			if ( cs.is( obj, 'object' ) ) ret = jQuery.extend( YES, ret, obj ); return ret;
		}
		return { $dummy : $dummy, $dummies : $dummies, $object : $object }
	} )( this );
	
}

})()